<?php
/**
 * 无限级Tree
 * 
 * @author flan
 *
 */
class MyTree {
	private $_aClass = array();
	private $_fi = 0;
	private $_type = 0; // 无排序  1为有排序
	
	/**
	 * 无限级Tree
	 * 
	 * @param array $aClass array(id => array(i => id, f=> fatherId, s => sortNum))
	 * @param int $fi
	 * @param int $type // 0无排序  1为有排序
	 */
	public function setTree($aClass, $fi=0, $type=0){
		$this->_aClass = $aClass;
		$this->_fi = $fi;
		$this->_type = $type;
		
		if ($this->_type == 1){
			$ii = 0;
			
			foreach ($aClass as &$aD){
				$ii++;
				if ($aD['s'] == 0){
					$aD['s'] = -$ii;
				}
			}
			$this->_aClass = $aClass;
		}
	}
	
	/**
	 * 返回关系数据
	 * 
	 * return array( id=> array(
	 * 	'i' => id
	 * 	'p' => path
	 * 	'c' => child
	 * 	'cc' > childAll
	 * ));
	 * 
	 */
	public function getTree(){
		
		$aClass0 = array();
		foreach ($this->_aClass as $i => &$aC){
			if ($aC['f'] == $this->_fi && $aC['f'] != ''){
				$aClass0[$i] = ($this->_type == 0) ? $i : $aC['s'];
				$aC['p'] = '';
			}else if ($aC['f'] != ''){
				$aC['p'] = implode(',', $this->dd($i, $aC['f'], array($aC['f'])));
				$this->_aClass[$aC['f']]['c'][$i] = intval(($this->_type == 0) ? $i : $aC['s']);
				$this->_aClass[$aC['f']]['cc'][] = $i;
			}
		}
		$this->_aClass[$this->_fi]['c'] = $aClass0;
		
		// 排序
		foreach ($this->_aClass as $i => &$aC){
			// 删除多余项
			if ($i != $this->_fi && !isset($aC['i'])){
				unset($this->_aClass[$i]);
			}
			if (isset($aC['c'])){
				if ($this->_type == 1){
					arsort($aC['c'], SORT_NUMERIC);
				}
				$aC['c'] = implode(',', array_keys($aC['c']));
			}
			
			if (isset($aC['cc'])){
				$aC['cc'] = implode(',', $aC['cc']);
			}
		}
		
		return $this->_aClass;
	}
	
	/**
	 * 递归查找路径
	 * 
	 * @param int $fid
	 * @param array $aClassPath
	 */
	private function dd($id, $fid, $aClassPath){
		if ($fid == $this->_fi){
			return $aClassPath;
		}
		$ffid = $this->_aClass[$fid]['f'];
		if ($ffid == '' || $ffid == $this->_fi){
			return $aClassPath;
		}
		
		$this->_aClass[$ffid]['cc'][] = $id;
		
		array_unshift($aClassPath, $ffid);
		return $this->dd($id, $ffid, $aClassPath);
	}
	
	/**
	 * 获取tree单条详细信息
	 *
	 * @param array $aTree tree 数组
	 * @param int $nTreeId ID
	 * @return
		 array(
			'id' => '',
			'name' => '',
			'path' => array('id' => 'name'), // 路径 包含自身
			'showList' => array('id' => 'name')// 子分类 ，无则为同级
			'c' => array( 'id' => 'name')// 子分类
			'level' => //等级 1 2 3...
			isLast => 是否为最后一级   1 为最后一级
		);
	 */
	static function getTreeOne($aTree, $nTreeId){
		$aTreeOne = $aTree[$nTreeId];
		
		$aRe = array(
			'id' => $nTreeId,
			'name' => $aTree[$nTreeId]['name'],
			'path' => array(),
			'showList' => array(),
			'c' => array(),
			'level' => 0,
			'isLast' => 0,
		);
		
		// 子项
		$aRe['c'] = self::getTreeIdName($aTree, $aTreeOne['c']);
		$aRe['showList'] = $aRe['c'];
		
		// 路径
		$aPath = self::getTreeIdName($aTree, $aTreeOne['p']);
		if ($aRe['id'] != '' && $aRe['name'] != ''){
			$aPath[$aRe['id']] = $aRe['name'];
		}
		$aRe['path'] = $aPath;
		
		// 无子项则显示同级
		if (count($aRe['showList']) == 0){
			$aTreeParent = $aTree[$aTreeOne['f']];
			$aRe['showList'] = self::getTreeIdName($aTree, $aTreeParent['c']);
		}
		
		// 等级
		$nLevel = 0;
		if ($aTreeOne['p'] == ''){
			$nLevel = 1;
		} else {
			$aP = explode(',', $aTreeOne['p']);
			$nLevel = count($aP) + 1;
		}
		$aRe['level'] = $nLevel;
		
		// 是否为最后一级
		$aRe['isLast'] = (count($aRe['c']) == 0) ? 1 : 0;
		
		return $aRe;
	}
	
	/**
	 * 取得子列表
	 *
	 * @param array $aTree tree 数组
	 * @param array / String $ids id字符串（，间隔） 或者id数组
	 * @return array(id => name)
	 */
	static function getTreeIdName($aTree, $ids){
		$aIds = array();
		if (is_array($ids)){
			$aIds = $ids;
		} else {
			if ($ids == ''){
				return array();
			}
			$aIds = explode(',', $ids);
		}
	
		$aRe = array();
		foreach ($aIds as $nId){
			$aRe[$nId] = $aTree[$nId]['name'];
		}
		return $aRe;
	}
}



/*
$aC = array(
	1 => array('i' => 1,'f' => 0, 's' => 4, 'name' => 'aaa'),
	2 => array('i' => 2,'f' => 0, 's' => 3),
	3 => array('i' => 3,'f' => 0, 's' => 2),
	4 => array('i' => 4,'f' => 0, 's' => 1),
	5 => array('i' => 5,'f' => 1, 's' => 1),
	6 => array('i' => 6,'f' => 2, 's' => 1),
	7 => array('i' => 7,'f' => 3, 's' => 1),
	8 => array('i' => 8,'f' => 4, 's' => 1),
	9 => array('i' => 9,'f' => 5, 's' => 1),
	10 => array('i' => 10,'f' => 6, 's' => 1),
	11 => array('i' => 11,'f' => 10, 's' => 1),
	12 => array('i' => 12,'f' => 10, 's' => 1),
	13 => array('i' => 13,'f' => 10, 's' => 1),
	14 => array('i' => 14,'f' => 7, 's' => 1),
	15 => array('i' => 15,'f' => 7, 's' => 1),
	16 => array('i' => 16,'f' => 15, 's' => 1),
	17 => array('i' => 17,'f' => 15, 's' => 1),
	18 => array('i' => 18,'f' => 15, 's' => 1),
	19 => array('i' => 19,'f' => 159, 's' => 1)
);

$pN = new myTree($aC);

print_r($pN->getTree());
*/

